`include "params.v"

module ram_test ();
	reg CLOCK=0;
	always #5 CLOCK = ~CLOCK;  // Create clock with period=10

	reg Reset = 1;
	reg RAMEnable;
	wire RWSelect, ReadClock, WriteClock;
	reg [`WD_RAM_ADDRESS-1:0] AddressRAM;
	wire [`WD_RAM_DATA-1:0] DataRAM;
	reg [`WD_RAM_DATA-1:0] DataRAM_reg;
	reg dummy;
	reg count, Clock1, Clock2;
	reg Init, Hold;
	reg TB_EN;
	reg Active;

	reg [`WD_DEPTH-1:0] ACSPage;
	reg [`WD_FSM-1:0] ACSSegment;

	assign WriteClock = (Active && ~dummy) ? Clock1:0;
	assign ReadClock = (Active && ~Hold) ? ~Clock1:0;
	assign DataRAM = DataRAM_reg;
	always @(posedge WriteClock)
		assign DataRAM_reg = DataRAM_reg + 1;

// Clock1 and Clock2
	always @(posedge CLOCK or negedge Reset)  begin
		if (~Reset) dummy <= 0;
		if (~Reset) RAMEnable <= 0;
		if (~Reset) Active <= 0; 				// a simple data input synchronizer
		if (~Reset) count <= 0;
		if (~Reset) AddressRAM <= 0;
		if (~Reset) DataRAM_reg <= 0;
		else count <= ~count;
	end

	assign RWSelect = (Clock2) ? 1:0;
	always @(posedge CLOCK or negedge Reset)
	begin
	   if (~Reset)
	     begin
	        Clock1 <= 0;
	        Clock2 <= 0;
	     end
	   else
	     begin
	       if (count) Clock1 <=~Clock1;
	       if (~count) Clock2 <= ~Clock2;
	     end
	end

	assign EVENT_1 = (ACSSegment == 6'h3E);
	assign EVENT_0 = (ACSSegment == 6'h3F);
	

	always @(posedge Clock2 or negedge Reset)
	   if (Active) dummy <= ~dummy;

	always @(posedge Clock1 or negedge Reset)
	begin
	  if (~Reset)
	     begin
	        {ACSPage,ACSSegment} <= 'hFFFFF;
	        Init <=0;
	        Hold <= 0;
	        TB_EN <= 0;
	     end
	  else if (Active)
	       begin
	          // Increase ACSSegment and Page
	          {ACSPage,ACSSegment} <= {ACSPage,ACSSegment} + 1;

	          // Init and Hold signal
			  // Hold是输出的信号
	          if (EVENT_1) begin Init <= 0; Hold <= 1; end
	           else if (EVENT_0) begin Init <= 1; Hold <= 0; end
	                 else begin {Init,Hold} <= 0; end

			  //63个幸存值产生之后，开始回溯。
	          if ((ACSSegment == 'h3F) && (ACSPage == 'h3E)) TB_EN <= 1;
	     end
	end

	initial begin
	   Reset = 1;
	   #30 Reset = 0;
	   #30 Reset = 1; Active = 1;
	end

	RAM ram(
		RAMEnable, AddressRAM, DataRAM, RWSelect, ReadClock, WriteClock
	);
endmodule

// File		: ram.v
/*-----------------------------------*/
  module RAM (RAMEnable, AddressRAM, DataRAM,
	           RWSelect, ReadClock, WriteClock);

//定义输入
input RAMEnable, RWSelect, ReadClock, WriteClock;
input [`WD_RAM_ADDRESS-1:0] AddressRAM; //11
inout [`WD_RAM_DATA-1:0] DataRAM; //8位地址线的输入

	//幸存存储实例化
	  RAMMODULE #(2048,8,11) ram (RAMEnable, DataRAM, AddressRAM, RWSelect,
	  				 ReadClock, WriteClock);

endmodule

/*-----------------------------------*/
  module RAMMODULE (_Enable, Data, Address, RWSelect, RClock, WClock);
//
// RAM Enable : Active Low。当Enable低电平Ram有效
parameter SIZE = 2048;
parameter DATABITS = 8;
parameter ADDRESSBITS = 7;

inout  [DATABITS-1:0] Data;
input  [ADDRESSBITS-1:0] Address;

input RWSelect;      // 0:Write     1:Read

input RClock,WClock,_Enable;

reg [DATABITS-1:0] Data_Regs [SIZE-1:0];
reg [DATABITS-1:0] DataBuff;

	// Write，下降沿有效
	always @(negedge WClock)
	begin
	   if (~_Enable) Data_Regs [Address] <= Data;
	end

	// Read，下降沿有效
	always @(negedge RClock)
	begin
		if (~_Enable) DataBuff <= Data_Regs [Address];
	end

	//RWSelect选择是否要用dataBuff
	assign Data = (RWSelect) ? DataBuff:'bz;

endmodule


/*-----------------------------------*/
  module METRICMEMORY (Reset, Clock1, Active, MMReadAddress,
	               MMWriteAddress, MMBlockSelect, MMMetric, MMPathMetric);
//
// 此模块存储度量值
/*-----------------------------------*/

//定义输入
input Reset, Clock1, Active, MMBlockSelect;
input [`WD_METR*`N_ACS-1:0] MMMetric; //32位数据
input [`WD_FSM-1:0] MMWriteAddress;
input [`WD_FSM-2:0] MMReadAddress;

//定义输出
input Reset, Clock1, Active, MMBlockSelect;
output [`WD_METR*2*`N_ACS-1:0] MMPathMetric;

//两块Ram
reg [`WD_METR*`N_ACS-1:0] M_REG_A [`N_ITER-1:0];
reg [`WD_METR*`N_ACS-1:0] M_REG_B [`N_ITER-1:0];

reg [`WD_METR*2*`N_ACS-1:0] MMPathMetric;

  always @(negedge Clock1 or negedge Reset)
  begin
	  //初始化Ram A, B
	 if (~Reset)
	    begin
	      M_REG_A [63] <= 0;M_REG_A [62] <= 0;M_REG_A [61] <= 0;
	      M_REG_A [60] <= 0;M_REG_A [59] <= 0;M_REG_A [58] <= 0;
	      M_REG_A [57] <= 0;M_REG_A [56] <= 0;
	      M_REG_A [55] <= 0;M_REG_A [54] <= 0;M_REG_A [53] <= 0;
	      M_REG_A [52] <= 0;M_REG_A [51] <= 0;
	      M_REG_A [50] <= 0;M_REG_A [49] <= 0;M_REG_A [48] <= 0;
	      M_REG_A [47] <= 0;M_REG_A [46] <= 0;
	      M_REG_A [45] <= 0;M_REG_A [44] <= 0;M_REG_A [43] <= 0;
	      M_REG_A [42] <= 0;M_REG_A [41] <= 0;
	      M_REG_A [40] <= 0;M_REG_A [39] <= 0;M_REG_A [38] <= 0;
	      M_REG_A [37] <= 0;M_REG_A [36] <= 0;
	      M_REG_A [35] <= 0;M_REG_A [34] <= 0;M_REG_A [33] <= 0;
	      M_REG_A [32] <= 0;M_REG_A [31] <= 0;
	      M_REG_A [30] <= 0;M_REG_A [29] <= 0;M_REG_A [28] <= 0;
	      M_REG_A [27] <= 0;M_REG_A [26] <= 0;
	      M_REG_A [25] <= 0;M_REG_A [24] <= 0;M_REG_A [23] <= 0;
	      M_REG_A [22] <= 0;M_REG_A [21] <= 0;
	      M_REG_A [20] <= 0;M_REG_A [19] <= 0;M_REG_A [18] <= 0;
	      M_REG_A [17] <= 0;M_REG_A [16] <= 0;
	      M_REG_A [15] <= 0;M_REG_A [14] <= 0;M_REG_A [13] <= 0;
	      M_REG_A [12] <= 0;M_REG_A [11] <= 0;
	 M_REG_A [10] <= 0;M_REG_A [9] <= 0;M_REG_A [8] <= 0;
	 M_REG_A [7] <= 0;M_REG_A [6] <= 0;
	 M_REG_A [5] <= 0;M_REG_A [4] <= 0;M_REG_A [3] <= 0;
	 M_REG_A [2] <= 0;M_REG_A [1] <= 0;
	 M_REG_A [0] <= 0;

	      M_REG_B [63] <= 0;M_REG_B [62] <= 0;M_REG_B [61] <= 0;
	      M_REG_B [60] <= 0;M_REG_B [59] <= 0;M_REG_B [58] <= 0;
	      M_REG_B [57] <= 0;M_REG_B [56] <= 0;
	      M_REG_B [55] <= 0;M_REG_B [54] <= 0;M_REG_B [53] <= 0;
	      M_REG_B [52] <= 0;M_REG_B [51] <= 0;
	      M_REG_B [50] <= 0;M_REG_B [49] <= 0;M_REG_B [48] <= 0;
	      M_REG_B [47] <= 0;M_REG_B [46] <= 0;
	      M_REG_B [45] <= 0;M_REG_B [44] <= 0;M_REG_B [43] <= 0;
	      M_REG_B [42] <= 0;M_REG_B [41] <= 0;
	      M_REG_B [40] <= 0;M_REG_B [39] <= 0;M_REG_B [38] <= 0;
	      M_REG_B [37] <= 0;M_REG_B [36] <= 0;
	      M_REG_B [35] <= 0;M_REG_B [34] <= 0;M_REG_B [33] <= 0;
	      M_REG_B [32] <= 0;M_REG_B [31] <= 0;
	      M_REG_B [30] <= 0;M_REG_B [29] <= 0;M_REG_B [28] <= 0;
	      M_REG_B [27] <= 0;M_REG_B [26] <= 0;
	      M_REG_B [25] <= 0;M_REG_B [24] <= 0;M_REG_B [23] <= 0;
	      M_REG_B [22] <= 0;M_REG_B [21] <= 0;
	      M_REG_B [20] <= 0;M_REG_B [19] <= 0;M_REG_B [18] <= 0;
	      M_REG_B [17] <= 0;M_REG_B [16] <= 0;
	      M_REG_B [15] <= 0;M_REG_B [14] <= 0;M_REG_B [13] <= 0;
	      M_REG_B [12] <= 0;M_REG_B [11] <= 0;
	 M_REG_B [10] <= 0;M_REG_B [9] <= 0;M_REG_B [8] <= 0;
	 M_REG_B [7] <= 0;M_REG_B [6] <= 0;
	 M_REG_B [5] <= 0;M_REG_B [4] <= 0;M_REG_B [3] <= 0;
	 M_REG_B [2] <= 0;M_REG_B [1] <= 0;
	 M_REG_B [0] <= 0;
	    end
	 else
	    begin
	      if (Active)
	         case (MMBlockSelect)//MMBlockSelect 用来选择某个Ram
	             0 : M_REG_A [MMWriteAddress] <= MMMetric;
				 1 : M_REG_B [MMWriteAddress] <= MMMetric;
	         endcase
	    end
	end

	always @(MMReadAddress or Reset)
	begin
	 if (~Reset) MMPathMetric <=0;
	  else begin
	    case (MMBlockSelect)
	      0 : case (MMReadAddress)
	            0 : MMPathMetric <= {M_REG_B [1],M_REG_B[0]};
	            1 : MMPathMetric <= {M_REG_B [3],M_REG_B[2]};
	            2 : MMPathMetric <= {M_REG_B [5],M_REG_B[4]};
	            3 : MMPathMetric <= {M_REG_B [7],M_REG_B[6]};
	            4 : MMPathMetric <= {M_REG_B [9],M_REG_B[8]};
	            5 : MMPathMetric <= {M_REG_B [11],M_REG_B[10]};
	            6 : MMPathMetric <= {M_REG_B [13],M_REG_B[12]};
	            7 : MMPathMetric <= {M_REG_B [15],M_REG_B[14]};

	            8 : MMPathMetric <= {M_REG_B [17],M_REG_B[16]};
	            9 : MMPathMetric <= {M_REG_B [19],M_REG_B[18]};
	           10 : MMPathMetric <= {M_REG_B [21],M_REG_B[20]};
	           11 : MMPathMetric <= {M_REG_B [23],M_REG_B[22]};
	           12 : MMPathMetric <= {M_REG_B [25],M_REG_B[24]};
	           13 : MMPathMetric <= {M_REG_B [27],M_REG_B[26]};
	           14 : MMPathMetric <= {M_REG_B [29],M_REG_B[28]};
	           15 : MMPathMetric <= {M_REG_B [31],M_REG_B[30]};

	           16 : MMPathMetric <= {M_REG_B [33],M_REG_B[32]};
	           17 : MMPathMetric <= {M_REG_B [35],M_REG_B[34]};
	           18 : MMPathMetric <= {M_REG_B [37],M_REG_B[36]};
	           19 : MMPathMetric <= {M_REG_B [39],M_REG_B[38]};
	           20 : MMPathMetric <= {M_REG_B [41],M_REG_B[40]};
	           21 : MMPathMetric <= {M_REG_B [43],M_REG_B[42]};
	           22 : MMPathMetric <= {M_REG_B [45],M_REG_B[44]};
	           23 : MMPathMetric <= {M_REG_B [47],M_REG_B[46]};

	           24 : MMPathMetric <= {M_REG_B [49],M_REG_B[48]};
	           25 : MMPathMetric <= {M_REG_B [51],M_REG_B[50]};
	           26 : MMPathMetric <= {M_REG_B [53],M_REG_B[52]};
	           27 : MMPathMetric <= {M_REG_B [55],M_REG_B[54]};
	           28 : MMPathMetric <= {M_REG_B [57],M_REG_B[56]};
	           29 : MMPathMetric <= {M_REG_B [59],M_REG_B[58]};
	           30 : MMPathMetric <= {M_REG_B [61],M_REG_B[60]};
	           31 : MMPathMetric <= {M_REG_B [63],M_REG_B[62]};
	         endcase

	      1 : case (MMReadAddress)
	            0 : MMPathMetric <= {M_REG_A [1],M_REG_A[0]};
	            1 : MMPathMetric <= {M_REG_A [3],M_REG_A[2]};
	            2 : MMPathMetric <= {M_REG_A [5],M_REG_A[4]};
	            3 : MMPathMetric <= {M_REG_A [7],M_REG_A[6]};
	            4 : MMPathMetric <= {M_REG_A [9],M_REG_A[8]};
	            5 : MMPathMetric <= {M_REG_A [11],M_REG_A[10]};
	            6 : MMPathMetric <= {M_REG_A [13],M_REG_A[12]};
	            7 : MMPathMetric <= {M_REG_A [15],M_REG_A[14]};

	            8 : MMPathMetric <= {M_REG_A [17],M_REG_A[16]};
	            9 : MMPathMetric <= {M_REG_A [19],M_REG_A[18]};
	           10 : MMPathMetric <= {M_REG_A [21],M_REG_A[20]};
	           11 : MMPathMetric <= {M_REG_A [23],M_REG_A[22]};
	           12 : MMPathMetric <= {M_REG_A [25],M_REG_A[24]};
	           13 : MMPathMetric <= {M_REG_A [27],M_REG_A[26]};
	           14 : MMPathMetric <= {M_REG_A [29],M_REG_A[28]};
	           15 : MMPathMetric <= {M_REG_A [31],M_REG_A[30]};

	           16 : MMPathMetric <= {M_REG_A [33],M_REG_A[32]};
	           17 : MMPathMetric <= {M_REG_A [35],M_REG_A[34]};
	           18 : MMPathMetric <= {M_REG_A [37],M_REG_A[36]};
	           19 : MMPathMetric <= {M_REG_A [39],M_REG_A[38]};
	           20 : MMPathMetric <= {M_REG_A [41],M_REG_A[40]};
	           21 : MMPathMetric <= {M_REG_A [43],M_REG_A[42]};
	           22 : MMPathMetric <= {M_REG_A [45],M_REG_A[44]};
	           23 : MMPathMetric <= {M_REG_A [47],M_REG_A[46]};

	           24 : MMPathMetric <= {M_REG_A [49],M_REG_A[48]};
	           25 : MMPathMetric <= {M_REG_A [51],M_REG_A[50]};
	           26 : MMPathMetric <= {M_REG_A [53],M_REG_A[52]};
	           27 : MMPathMetric <= {M_REG_A [55],M_REG_A[54]};
	           28 : MMPathMetric <= {M_REG_A [57],M_REG_A[56]};
	           29 : MMPathMetric <= {M_REG_A [59],M_REG_A[58]};
	           30 : MMPathMetric <= {M_REG_A [61],M_REG_A[60]};
	           31 : MMPathMetric <= {M_REG_A [63],M_REG_A[62]};
	         endcase
	  endcase
	  end
	end

endmodule
